﻿namespace HzySocket.WebSocket.Core
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;

    /// <summary>
    /// session 容器
    /// </summary>
    /// <typeparam name="TSession"></typeparam>
    public static class WebSocketSessionContainer<TSession> where TSession : WebSocketSessionBase
    {
        //定义静态对象 缓存 WebSocket 对象
        public static readonly List<TSession> AppSessions;

        /// <summary>
        /// 
        /// </summary>
        static WebSocketSessionContainer()
        {
            if (AppSessions == null) AppSessions = new List<TSession>();
        }

        /// <summary>
        /// 根据条件筛选 Session 对象
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static IEnumerable<TSession> GetAppSessions(Func<TSession, bool> predicate)
        {
            lock (AppSessions)
            {
                return AppSessions.Where(predicate);
            }
        }

        /// <summary>
        /// 获取 所有 session 对象
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<TSession> GetAllAppSessions()
        {
            lock (AppSessions)
            {
                return AppSessions;
            }
        }

        /// <summary>
        /// 插入Session 对象
        /// </summary>
        /// <param name="appSession"></param>
        public static void AddAppSession(TSession appSession)
        {
            lock (AppSessions)
            {
                AppSessions.Add(appSession);
            }
        }

        /// <summary>
        /// 添加或者更新
        /// </summary>
        /// <param name="appSession"></param>
        public static void AddOrUpdateAppSession(TSession appSession)
        {
            lock (AppSessions)
            {
                var _OldAppSession = GetAppSessions(w => w.SessionKey == appSession.SessionKey).FirstOrDefault();
                if (_OldAppSession == null)
                {
                    AddAppSession(appSession);
                }
                else
                {
                    _OldAppSession = appSession;
                }
            }
        }

        /// <summary>
        /// 移除Session 对象
        /// </summary>
        /// <param name="predicate"></param>
        public static void RemoveSession(Func<TSession, bool> predicate)
        {
            lock (AppSessions)
            {
                var _AppSessions = GetAppSessions(predicate)?.ToList();
                if (_AppSessions == null) return;

                for (int i = 0; i < _AppSessions.Count(); i++)
                {
                    var item = _AppSessions[i];
                    AppSessions.Remove(item);
                }
            }
        }

        /// <summary>
        /// 获取 session 连接数
        /// </summary>
        /// <returns></returns>
        public static int GetAppSessionCount()
        {
            lock (AppSessions)
            {
                return AppSessions.Count;
            }
        }

        /// <summary>
        /// 检查 session 是否存在
        /// </summary>
        /// <returns></returns>
        public static bool Any(Func<TSession, bool> predicate)
        {
            lock (AppSessions)
            {
                return AppSessions.Any(predicate);
            }
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="Data"></param>
        public static async Task SendAsync<T>(Func<TSession, bool> predicate, T Data)
        {
            var _appSessions = GetAppSessions(predicate).ToList();

            for (int i = 0; i < _appSessions.Count; i++)
            {
                var item = _appSessions[i];
                await item?.SendAsync(Data);
            }
        }

        /// <summary>
        /// 所有连接用户发送消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="Data"></param>
        public static async Task SendAllAsync<T>(T Data)
        {
            var _appSessions = GetAllAppSessions().ToList();

            for (int i = 0; i < _appSessions.Count; i++)
            {
                var item = _appSessions[i];
                await item?.SendAsync(Data);
            }
        }





    }
}
